package tcp;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;

/**
 * 我们使用了边长的加特殊字符\r\n区分了不同请求，所以可以处理长连接
 *
 **/
//服务器操作
public class 长连接Server {
    private static final HashMap<String,String> map=new HashMap<>();
    static {
        map.put("apple","苹果");
        map.put("banana","香蕉");
    }
    public static void main(String[] args) throws IOException {
        //1.开店（创建socket）
        Log.println("服务器启动，监听在TCP：9090 端口");
        ServerSocket serverSocket = new ServerSocket(9090);//UDP的8080端口绑定不影响TCP的使用，端口的唯一绑定是和协议有关系的
        //进行循环
        while(true) {
            //TCP和UDP不一样的点，TCP是面向连接的，所以需要先进行连接
            //1.接通连接（电话）——accept
            Log.println("等待客户端连接上来");
            Socket socket=serverSocket.accept();//会有阻塞
            Log.println("有新的客户端连接上来");
            InetAddress inetAddress=socket.getInetAddress();
            Log.println("对方的IP地址是"+inetAddress);
            int port = socket.getPort();
            System.out.println("对方的端口是"+port);
            InputStream is=socket.getInputStream();//进行处理，拿到输入流，从输入流中进行读数据
            Scanner scanner=new Scanner(is,"UTF-8");
            OutputStream os = socket.getOutputStream();//os:用于写数据
            //OutputStream->OutputStreamWriter->PrintWriter
            OutputStreamWriter writer=new OutputStreamWriter(os,"UTF-8");
            PrintWriter printWriter=new PrintWriter(writer);


            //在同一个连接中进行不断的读请求，处理业务，发送响应
            //循环结束条件：对方不再发请求就结束了。怎么不再发了：自己设计
            //客户端client挂断电话，表示本次连接的请求响应处理结束
            //客户端挂电话怎么体现—客户端通过关闭连接的方式来体现
            //怎么知道关闭连接了—输入流读不到了，或者说is读到了EOS(-1)
            while(scanner.hasNextLine()) {//我们已经封装成Scanner了，只要hasNextline()返回false就是没有下一行了
                //2.读取请求
                //字节形式不好读，封装成字符形式读取
                String header = scanner.nextLine();//"我是Java19班的\r\n",同时nextLine()会帮忙把换行符去掉
                //TODO:像UDP一样，应该做一个请求格式检查，看读到的header是否是正确的，不是的话不应该处理请求
                String englishWord = scanner.nextLine();
                Log.println("英文单词" + englishWord);
                //3.处理业务
                //读到了开始进行业务翻译
                String chinseWord = map.getOrDefault(englishWord, "不认识");
                Log.println("中文单词" + chinseWord);
                //4.发送响应
                //好的\r\n苹果\r\n；把OutputStream进行对象的封装

                Log.println("服务器进行发送");
                printWriter.printf("好的\r\n%s\r\n", chinseWord);
                printWriter.flush();//不要忘记flush刷新
                Log.println("服务器发送成功");
            }
            socket.close();//上面无论是读还是响应都没关闭，统一调用close()连输入流和输出流都关掉了
        }
    }
}
